use crate::cljcell::clj_cell::CljCell;
use crate::lexer::clj_lexer::CljLexer;
use std::rc::Rc;

/**
 * 生成 clojure ast
 * */
pub struct MyClojureReader<'a> {
    lex: CljLexer<'a>
}

impl <'a> MyClojureReader<'a> {
    pub fn new(lex: CljLexer<'a>) -> Self {
        Self {
            lex: lex
        }
    }

    pub fn get_expression(&mut self) -> Rc<CljCell> {
        if self.lex.next() == false {
            return Rc::new(CljCell::Null);
        }
        return Rc::new(self.parse_expression(&CljCell::Null).unwrap());
    }

    pub fn parse_list_body(&mut self, ct: CljCell) -> CljCell {
        let token_item = self.lex.current();
        if let CljCell::RparenClj = token_item {
            return CljCell::Null;
        } else {
            let mut lst:Vec<Rc<CljCell>> = Vec::new();
            let e1 = self.parse_expression(&ct).unwrap();

            if let CljCell::Null = e1 {
                return CljCell::Null;
            } else {
                lst.push(Rc::new(e1));
            }
            while self.lex.next() {
                //println!("{:?}", self.lex.current());
                let e2 = self.parse_expression(&ct).unwrap();
                //println!("{:?}", e2);
                if let CljCell::Null = e2 {
                    break;
                } else {
                    lst.push(Rc::new(e2));
                }
            }
            return CljCell::CljList (lst);
        }
        //return CljCell::Null;
    }

    pub fn parse_bracket_body(&mut self, ct: CljCell) -> CljCell {
        let token_item = self.lex.current();
        if let CljCell::RbracketClj = token_item {
            return CljCell::Null;
        } else {
            let mut lst:Vec<Rc<CljCell>> = Vec::new();
            let e1 = self.parse_expression(&ct).unwrap();
            if let CljCell::Null = e1 {
                return CljCell::Null;
            } else {
                lst.push(Rc::new(e1));
            }
            while self.lex.next() {
                let e2 = self.parse_expression(&ct).unwrap();
                if let CljCell::Null = e2 {
                    break;
                } else {
                    lst.push(Rc::new(e2));
                }
            }
            return CljCell::BracketClj(lst);
        }
        //return CljCell::Null;
    }

    pub fn parse_braces_body(&mut self, ct: CljCell) -> CljCell {
        let token_item = self.lex.current();
        if let CljCell::RbracesClj = token_item {
            return CljCell::Null;
        } else {
            let mut lst:Vec<Rc<CljCell>> = Vec::new();
            let e1 = self.parse_expression(&ct).unwrap();
            if let CljCell::Null = e1 {
                return CljCell::Null;
            } else {
                lst.push(Rc::new(e1));
            }
            while self.lex.next() {
                let e2 = self.parse_expression(&ct).unwrap();
                if let CljCell::Null = e2 {
                    break;
                } else {
                    lst.push(Rc::new(e2));
                }
            }

            return CljCell::BracesClj(lst);
        }
        //return CljCell::Null;
    }

    pub fn parse_expression(&mut self, ct: &CljCell) -> Result<CljCell, String> {
        let token_item = self.lex.current();
        match token_item {
            CljCell::RparenClj => {
                match ct {
                    CljCell::LparenClj => return Ok(CljCell::Null),
                    _ => return Err(token_item.to_string()),
                }
            },
            CljCell::RbracketClj => {
                if let CljCell::LbracketClj = ct {
                    return Ok(CljCell::Null);
                }
                return Err(token_item.to_string());
            },
            CljCell::RbracesClj => {
                if let CljCell::LbracesClj = ct {
                    return Ok(CljCell::Null);
                }
                return Err(token_item.to_string());
            },
            CljCell::LparenClj => {
                self.lex.next();
                let cell = self.parse_list_body(CljCell::LparenClj);
                if let CljCell::Null = cell {
                    let mut ps = String::from("错误：行号位置：");
                    ps.push_str(format!("{}", self.lex.get_line_number()).as_str());
                    ps.push_str(" 行内位置：");
                    ps.push_str(format!("{}", self.lex.get_line_index()).as_str());
                    return Err(ps);
                } else {
                    return Ok(cell);
                }
            },
            CljCell::LbracketClj => {
                self.lex.next();
                let cell = self.parse_bracket_body(CljCell::LbracketClj);
                if let CljCell::Null = cell {
                    let mut ps = String::from("错误：行号位置：");
                    ps.push_str(format!("{}", self.lex.get_line_number()).as_str());
                    ps.push_str(" 行内位置：");
                    ps.push_str(format!("{}", self.lex.get_line_index()).as_str());
                    return Err(ps);
                } else {
                    return Ok(cell);
                }
            },
            CljCell::LbracesClj => {
                self.lex.next();
                let cell = self.parse_braces_body(CljCell::LbracesClj);
                if let CljCell::Null = cell {
                    let mut ps = String::from("错误：行号位置：");
                    ps.push_str(format!("{}", self.lex.get_line_number()).as_str());
                    ps.push_str(" 行内位置：");
                    ps.push_str(format!("{}", self.lex.get_line_index()).as_str());
                    return Err(ps);
                } else {
                    return Ok(cell);
                }
            },
            CljCell::Sharp => {
                self.lex.next();
                let token_item1 = self.lex.current();
                match token_item1 {
                    CljCell::LparenClj => {
                        let m1 = self.parse_expression(&CljCell::LparenClj).unwrap();
                        match m1 {
                            CljCell::CljList (vs) => return Ok(CljCell::Anonymous (vs)),
                            _ => {
                                let mut ps = String::from("错误：行号位置：");
                                ps.push_str(format!("{}", self.lex.get_line_number()).as_str());
                                ps.push_str(" 行内位置：");
                                ps.push_str(format!("{}", self.lex.get_line_index()).as_str());
                                return Err(ps);
                            },
                        }
                    },
                    CljCell::BracesClj(m) => {
                        let m1 = self.parse_expression(&CljCell::LbracesClj).unwrap();
                        match m1 {
                            CljCell::BracesClj(m) => return Ok(CljCell::Set (m)),
                            _ => {
                                let mut ps = String::from("错误：行号位置：");
                                ps.push_str(format!("{}", self.lex.get_line_number()).as_str());
                                ps.push_str(" 行内位置：");
                                ps.push_str(format!("{}", self.lex.get_line_index()).as_str());
                                return Err(ps);
                            },
                        }
                    },
                    _ => {
                        let mut ps = String::from("错误：行号位置：");
                        ps.push_str(format!("{}", self.lex.get_line_number()).as_str());
                        ps.push_str(" 行内位置：");
                        ps.push_str(format!("{}", self.lex.get_line_index()).as_str());
                        return Err(ps);
                    },
                }
            },
            CljCell::QuoteList => {
                self.lex.next();
                let token = self.lex.current();
                let ptr: *mut MyClojureReader = self as *const MyClojureReader as *mut MyClojureReader;
                unsafe {
                    let m1 = (*ptr).parse_expression(token).unwrap();
                    return Ok(CljCell::QuoteListVs(Rc::new(m1)));
                }
            },
            CljCell::Quote => {
                // "'"  ' 阻止表达式求值 例如：'if 或者是 '() 当初一个序列
                self.lex.next();
                let mut token = self.lex.current();
                if let CljCell::LparenClj = token {
                    // '() 是这种情况
                    self.lex.next();
                    let m1 = self.parse_expression(&CljCell::LparenClj).unwrap();
                    match m1 {
                        CljCell::CljList (vs) => return Ok(CljCell::List (vs)),
                        _ => {
                            let mut ps = String::from("错误：行号位置：");
                            ps.push_str(format!("{}", self.lex.get_line_number()).as_str());
                            ps.push_str(" 行内位置：");
                            ps.push_str(format!("{}", self.lex.get_line_index()).as_str());
                            return Err(ps);
                        },
                    }
                } else {
                    let ptr: *mut MyClojureReader = self as *const MyClojureReader as *mut MyClojureReader;
                    unsafe {
                        let m1 = (*ptr).parse_expression(token).unwrap();
                        return Ok(CljCell::QuoteVs(Rc::new(m1)));
                    }
                }
                return Ok(CljCell::Quote);
            },
            CljCell::Unquote => {
                // "~"  ~ 例如： ~test
                //self.lex.next();
                //return Ok(CljCell::Unquote);
                self.lex.next();
                let token = self.lex.current();

                let ptr: *mut MyClojureReader = self as *const MyClojureReader as *mut MyClojureReader;
                unsafe {
                    let m1 = (*ptr).parse_expression(token).unwrap();
                    return Ok(CljCell::UnquoteVs(Rc::new(m1)));
                }
            },
            CljCell::UnquoteList => {
                // ~@ 对序列求值，并展开
                //return Ok(CljCell::UnquoteList);
                self.lex.next();
                let token = self.lex.current();
                let ptr: *mut MyClojureReader = self as *const MyClojureReader as *mut MyClojureReader;
                unsafe {
                    let m1 = (*ptr).parse_expression(token).unwrap();
                    return Ok(CljCell::UnquoteListVs(Rc::new(m1)));
                }
            },
            CljCell::AndClj => return Ok(CljCell::AndClj),
            CljCell::Defmacro => return Ok(CljCell::Defmacro),
            CljCell::Defn => return Ok(CljCell::Defn),
            CljCell::FnClj => return Ok(CljCell::FnClj),
            CljCell::DefClj => return Ok(CljCell::DefClj),
            CljCell::LetClj => return Ok(CljCell::LetClj),
            CljCell::Cond => return Ok(CljCell::Cond),
            CljCell::IfClj => return Ok(CljCell::IfClj),
            CljCell::FirstClj => return Ok(CljCell::FirstClj),
            CljCell::LastClj => return Ok(CljCell::LastClj),
            CljCell::RestClj => return Ok(CljCell::RestClj),
            CljCell::DoClj => return Ok(CljCell::DoClj),
            CljCell::LoopClj => return Ok(CljCell::LoopClj),
            CljCell::Recur => return Ok(CljCell::Recur),
            CljCell::Apply => return Ok(CljCell::Apply),
            CljCell::MapClj => return Ok(CljCell::MapClj),
            CljCell::Cons => return Ok(CljCell::Cons),
            CljCell::ReduceClj => return Ok(CljCell::ReduceClj),
            CljCell::Eval => return Ok(CljCell::Eval),
            CljCell::Addition => return Ok(CljCell::Addition),
            CljCell::Subtraction => return Ok(CljCell::Subtraction),
            CljCell::Multiplication => return Ok(CljCell::Multiplication),
            CljCell::Division => return Ok(CljCell::Division),
            CljCell::Symbol (vs) => return Ok(CljCell::Symbol (Rc::new(vs.to_string()))),
            CljCell::KeySymbol (vs) => return Ok(CljCell::KeySymbol (Rc::new(vs.to_string()))),
            CljCell::StringClj (vs) => return Ok(CljCell::StringClj (Rc::new(vs.to_string()))),
            CljCell::NumberClj(m) => return Ok(CljCell::NumberClj(Rc::new(m.to_string()))),
            CljCell::BooleanClj (vs) => return Ok(CljCell::BooleanClj (*vs)),
            CljCell::LongClj (vs) => return Ok(CljCell::LongClj (*vs)),
            CljCell::DoubleClj (vs) => return Ok(CljCell::DoubleClj (*vs)),
            CljCell::IntClj (vs) => return Ok(CljCell::IntClj (*vs)),
            CljCell::FloatClj (vs) => return Ok(CljCell::FloatClj (*vs)),
            CljCell::StringFunc => return Ok(CljCell::StringFunc),
            CljCell::NumberFunc => return Ok(CljCell::NumberFunc),
            CljCell::BooleanFunc => return Ok(CljCell::BooleanFunc),
            CljCell::DateFunc => return Ok(CljCell::DateFunc),
            CljCell::IntFunc => return Ok(CljCell::IntFunc),
            CljCell::LongFunc => return Ok(CljCell::LongFunc),
            CljCell::CharFunc => return Ok(CljCell::CharFunc),
            CljCell::ShortFunc => return Ok(CljCell::ShortFunc),
            CljCell::ByteFunc => return Ok(CljCell::ByteFunc),
            CljCell::DoubleFunc => return Ok(CljCell::DoubleFunc),
            CljCell::FloatFunc => return Ok(CljCell::FloatFunc),
            CljCell::NotClj => return Ok(CljCell::NotClj),
            CljCell::Nil => return Ok(CljCell::Nil),
            CljCell::IsNil => return Ok(CljCell::IsNil),
            CljCell::AndLgClj => return Ok(CljCell::AndLgClj),
            CljCell::OrLgClj => return Ok(CljCell::OrLgClj),
            CljCell::EqualsLgClj => return Ok(CljCell::EqualsLgClj),
            CljCell::GreaterThanLgClj => return Ok(CljCell::GreaterThanLgClj),
            CljCell::LessThanLgClj => return Ok(CljCell::LessThanLgClj),
            CljCell::GreaterEqualsLgClj => return Ok(CljCell::GreaterEqualsLgClj),
            CljCell::LessEqualsLgClj => return Ok(CljCell::LessEqualsLgClj),
            CljCell::ElseClj => return Ok(CljCell::ElseClj),
            //CljCell::PrintlnClj => return Ok(CljCell::PrintlnClj),
            CljCell::Percent(my_ptr) => {
                let ptr = my_ptr.as_ref().unwrap();
                if let CljCell::IntClj(vs_index) = **ptr {
                    return Ok(CljCell::Percent(Some(Box::new(CljCell::IntClj(vs_index)))));
                } else {
                    let mut ps = String::from("错误：行号位置：");
                    ps.push_str(format!("{}", self.lex.get_line_number()).as_str());
                    ps.push_str(" 行内位置：");
                    ps.push_str(format!("{}", self.lex.get_line_index()).as_str());
                    return Err(ps);
                }
                //return Ok(CljCell::Percent{vs_index: vec![vs_index[0]], has_vs: *has_vs});
            },
            _ => return Ok(CljCell::Null),
        }
    }

     fn unsafe_convert(&self, ref_box: &Box<CljCell>) -> Box<CljCell> {
         unsafe {
             Box::from_raw(ref_box.as_ref() as *const CljCell as *mut CljCell)
         }
    }
}














































